/*===============================================================================

    lrntree.h  -  Copyright (C) 1998-2005 by Don Cross

    This is a new module for learning new openings.
    This file replaces the old file 'learn.cpp'.
    Now, instead of reading the entire tree into memory, we encapsulate
    direct I/O to a binary file which contains the tree.  This saves
    a lot of dynamic memory and prevents us from having to read and write
    the entire tree all at once.

=============================================================================*/
#ifndef __ddc_chenard_lrntree_h
#define __ddc_chenard_lrntree_h


const char * const DEFAULT_CHENARD_TREE_FILENAME = "chenard.trx";


struct LearnBranch
{
    Move   move;              // The move source, dest, and score of this branch
    INT32  timeAnalyzed;      // Amount of time move was analyzed in centiseconds
    INT32  winsAndLosses;     // +1 for every White win, -1 for every Black win
    INT32  child;             // first branch which is a child of this one
    INT32  sibling;           // immediate sibling to this branch
    INT32  nodesEvaluated;    // number of nodes evaluated by computer
    INT32  numAccesses;       // number of times this move played by computer
    INT32  reserved [2];      // ... and some room to grow

    LearnBranch():
        timeAnalyzed (0),
        winsAndLosses (0),
        child (-1),
        sibling (-1),
        nodesEvaluated (0),
        numAccesses (0)
    {
        move.source = 0;
        move.dest = 0;
        move.score = 0;
        reserved[0] = 0;
        reserved[1] = 0;
    }
};


const long LearnBranchFileSize = 9*4;   // number of bytes per file record

const unsigned MaxLearnDepth = 30;

class LearnTree
{
public:
    LearnTree():  f(0) {}
    ~LearnTree();

    // NOTE:  All 'int' functions return 0 on failure, 1 on success.

    // High-level functions...

    bool familiarPosition (
        ChessBoard &board,
        Move &bestmove,
        long timeLimit,
        const MoveList & );   // legal moves: included so we can do sanity check

    // Returns the following values:
    //    0 = Tree not changed
    //    1 = Modified an existing branch
    //    2 = Added a new branch

    int rememberPosition (
        ChessBoard      &board,
        Move            bestmove,
        long            timeLimit,
        unsigned long   nodesEvaluated,
        unsigned long   numAccesses,
        long            winsAndLosses );

    void learnFromGame (
        ChessBoard &board,
        ChessSide winner );

    void absorbFile ( const char *gameFilename );

    void trainer (
        ComputerChessPlayer *whitePlayer,
        ComputerChessPlayer *blackPlayer,
        ChessBoard &board,
        ChessUI &ui,
        INT32 timeLimit );

    static int Pack ( 
        const char  *inTreeFilename,
        const char  *outTreeFilename,
        SCORE       window );

    int  open ( const char *filename );
    int  read  ( INT32 offset, LearnBranch & );
    int  write ( INT32 offset, const LearnBranch & );
    INT32  numNodes();

protected:
    void absorbGameFile ( const char *gameFilename );
    void absorbPgnFile  ( const char *pgnFileName );

    int  create ( const char *filename );
    int  flush();
    int  close();

    // Low-level functions...

    int append ( INT32 &offset, const LearnBranch & );

    int insert ( LearnBranch &branch, INT32 parent, INT32 &offset );

    int  write ( INT32 );
    int  read  ( INT32 & );
    int  write ( Move );
    int  read  ( Move & );

    INT32  numNodesAtDepth (
        INT32 root,
        int targetDepth,
        int currentDepth,
        INT32 searchTime,
        ChessBoard & );

    void trainDepth (
        INT32 offset,
        INT32 timeLimit,
        ChessUI &ui,
        ComputerChessPlayer *whitePlayer,
        ComputerChessPlayer *blackPlayer,
        ChessBoard &board,
        int targetDepth,
        int currentDepth );

    int packer (
        INT32       offset,
        LearnTree   &outTree,
        int         depth,
        ChessBoard  &board,
        SCORE       window );       // maximum absolute value of score allowed

    // the following function is used for auto-verification purposes...

    bool locateAndReadBranch (
        ChessBoard      &board,
        Move            moveToFind,
        LearnBranch     &branch );

    void checkForPause();

private:
    FILE *f;
};


#endif // __ddc_chenard_lrntree_h
